module Main where

import CPUDefs
import CPU

import System.IO
import Data.Array.IO
import Data.STRef
import Control.Monad.Reader
import Control.Monad.ST

readProgram :: FilePath -> IO [Operand]
readProgram file = do
    fd  <- openBinaryFile file ReadMode
    fs  <- hFileSize fd
    arr <- newArray_ (0,fromIntegral fs)
    hGetArray fd arr $ fromIntegral fs
    elems <- getElems arr
    return $ map fromIntegral elems

main :: IO ()
main = do
    ops <- readProgram "fil.asm"
    putStrLn $ show $ run ops

run :: [Operand] -> Integer
run = runST (do
        mem     <- initMem >>= \m -> insertCode m >> newSTRef m
        cpu     <- newSTRef initCPU
        runReaderT (loop 0) (mem,cpu)
        )

loop :: Integer -> NES s Integer
loop n = do
    op <- fetch
    if op == 0xEA
        then return n
        else do
            c <- execute op
            loop $! n+(fromIntegral c)

initMem :: ST s (Memory s)
initMem = do
    low     <- newArray (0x0000,0x07FF) 0xEA >>= newSTRef
    ppu     <- newArray (0x2000,0x2007) 0xEA >>= newSTRef
    high    <- newArray (0x4000,0xFFFF) 0xEA >>= newSTRef
    return $ Memory low ppu high

initCPU :: CPU
initCPU = CPU 0 0 0 0 0x5000 (Status False False False False False False False)


opCodes :: [(Address,Operand)]
opCodes = zip [0x5000..] codes
    where
        codes = [
            0xA9, -- 5000:      LDA #$FF
            0xFF,
            0xA2, -- 5002:      LDX #$FF
            0xFF,
            0xA0, -- 5004:      LDY #$FF
            0xFF, 
            0x88, -- 5006:      DEY
            0xD0, -- 5007:      BNE 5006
            0xFD, 
            0xCA, -- 5009:      DEX
            0xD0, -- 500A:      BNE 5004
            0xF8, 
            0xFF, -- 500C:      DECA
            0xD0, -- 500D:      BNE 5002
            0xF3,
            0xEA  -- 500F:      NOP
            ]
